﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XCoder
{
    /// <summary>
    /// 数据库信息
    /// </summary>
    public class DatabaseInfo
    {
        #region 属性

        /// <summary>
        /// 获取或设置数据库名称
        /// </summary>
        public string DatabaseName { get; private set; }

        /// <summary>
        /// 获取数据库类型
        /// </summary>
        public System.Data.DatabaseType DatabaseType { get; private set; }

        /// <summary>
        /// 获取或设置数据库连接字符串
        /// </summary>
        public string ConnectionString { get; private set; }

        /// <summary>
        /// 获取或设置是否允许可空类型
        /// </summary>
        public bool AllowTypeNullable { get; set; }

        /// <summary>
        /// 是否生成 Model 的 Load 方法
        /// </summary>
        public bool Generate_Model_Load_Method { get; set; }

        /// <summary>
        /// 是否生成 Model 的 LoadDataRow 方法
        /// </summary>
        public bool Generate_Model_LoadDataRow_Method { get; set; }

        /// <summary>
        /// 是否生 Model 的 Compare 方法
        /// </summary>
        public bool Generate_Model_Compare_Method { get; set; }

        /// <summary>
        /// 数据库帮助类对象名称
        /// </summary>
        public string DbHelperObjectName { get; set; }

        public string ModelNameSpace { get; set; }

        public string DALNameSpace { get; set; }

        public string BLLNameSpace { get; set; }

        private System.Data.DbHelper _helper;
        /// <summary>
        /// 获取数据库帮助类
        /// </summary>
        public System.Data.DbHelper Helper
        {
            get
            {
                if (this._helper == null)
                    this._helper = new System.Data.DbHelper(this.DatabaseType, this.ConnectionString);
                return _helper;
            }
        }

        private System.Collections.Generic.List<TableInfo> tables;
        /// <summary>
        /// 获取或设置数据库表
        /// </summary>
        public System.Collections.Generic.List<TableInfo> Tables
        {
            get
            {
                if (this.tables == null)
                    this.tables = new System.Collections.Generic.List<TableInfo>();
                return tables;
            }
        }

        #endregion

        #region 缓存

        private System.Data.DataTable _indexColumnsSource;
        /// <summary>
        /// 获取索引列
        /// </summary>
        public System.Data.DataTable IndexColumnsSource
        {
            get
            {
                if (this._indexColumnsSource == null)
                {
                    this._indexColumnsSource = new System.Data.DataTable();
                    try
                    {
                        this._indexColumnsSource = this.Helper.GetIndexColumns();
                    }
                    catch { }
                }
                return _indexColumnsSource;
            }
        }

        private System.Data.DataTable _dataTypesSource;
        /// <summary>
        /// 获取数据类型架构集合
        /// </summary>
        public System.Data.DataTable DataTypesSource
        {
            get
            {
                if (this._dataTypesSource == null)
                    this._dataTypesSource = this.Helper.GetDataTypes();
                return _dataTypesSource;
            }
        }

        private System.Data.DataTable _tablesSource;
        /// <summary>
        /// 获取表架构集合
        /// </summary>
        public System.Data.DataTable TablesSource
        {
            get
            {
                if (this._tablesSource == null)
                    this._tablesSource = this.Helper.GetTables();
                return _tablesSource;
            }
        }

        private System.Data.DataTable _columnsSource;
        /// <summary>
        /// 获取列架构集合
        /// </summary>
        public System.Data.DataTable ColumnsSource
        {
            get
            {
                if (this._columnsSource == null)
                    this._columnsSource = this.Helper.GetColumns();
                return _columnsSource;
            }
        }
        private System.Data.DataTable _properties;
        /// <summary>
        /// 获取扩展属性
        /// </summary>
        public System.Data.DataTable Properties
        {
            get
            {
                if (this._properties == null)
                {
                    this._properties = this.Helper.GetExtended_Properties();
                }
                return _properties;
            }
        }

        #endregion

        private DatabaseInfo()
        {
            this.AllowTypeNullable = true;
            this.Generate_Model_Load_Method = true;
            this.Generate_Model_LoadDataRow_Method = true;
            this.Generate_Model_Compare_Method = true;
            this.ModelNameSpace = "ModelNameSpace";
            this.DALNameSpace = "DALNameSpace";
            this.BLLNameSpace = "BLLNameSpace";
            this.DbHelperObjectName = "DbHelperObjectName";
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="databaseName"></param>
        /// <param name="dbType"></param>
        /// <param name="connectionString"></param>
        public DatabaseInfo(string databaseName, System.Data.DatabaseType dbType, string connectionString)
            : this()
        {
            this.DatabaseName = databaseName;
            this.DatabaseType = dbType;
            this.ConnectionString = connectionString;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public System.Collections.Generic.List<TableInfo> GetTables()
        {
            try
            {
                //  打开数据库连接
                this.Helper.Open();

                #region 获取相关架构信息

                //  获取数据类型架构集合
                var xDataTypes = XDataType.Parse(this.DataTypesSource, this.DatabaseType);
                //  获取表架构集合
                var xTables = XTable.Parse(this.TablesSource, this.DatabaseType);
                //  获取列架构集合
                var xColumns = XColumn.Parse(this.ColumnsSource, this.DatabaseType);
                //  获取索引列架构集合
                var xIndexColumns = XIndexColumn.Parse(this.IndexColumnsSource, this.DatabaseType);
                //  获取扩展属性
                var xProperties = XExtended_Property.Parse(this.Properties, this.DatabaseType);

                #endregion

                //  关闭数据库连接
                this.Helper.Close();

                //  清空表信息
                this.Tables.Clear();
                //  遍历表架构集合
                foreach (XTable t in xTables)
                {
                    var tableInfo = new TableInfo(this, t.TableName, t.TableName) { IsView = t.IsView };
                    //  查找扩展属性
                    var tableProperty = xProperties.Find(x => x.TableName == t.TableName && string.IsNullOrEmpty(x.ColumnName));
                    if (tableProperty != null)
                        tableInfo.Comment = tableProperty.Value;
                    //  查找字段
                    var tableColumns = xColumns.FindAll(x => string.Equals(x.TableName, t.TableName, StringComparison.CurrentCultureIgnoreCase));
                    //  字段排序
                    tableColumns.Sort((a, b) => { return a.Ordinal - b.Ordinal; });
                    //  遍历字段
                    tableColumns.ForEach(c =>
                    {
                        //  查找索引
                        var columnIndexs = xIndexColumns.FindAll(x => x.TableName == c.TableName && x.ColumnName == c.ColumnName);
                        var columnType = xDataTypes.Find(x => x.TypeName == c.DataType || x.TypeID.ToString() == c.DataType);
                        var columnProperty = xProperties.Find(x => x.TableName == c.TableName && x.ColumnName == c.ColumnName);

                        var columnInfo = new ColumnInfo(tableInfo, c.ColumnName, c.ColumnName);
                        columnInfo.Comment = columnProperty != null ? columnProperty.Value : c.ColumnName;
                        columnInfo.DataType = c.DataType;
                        columnInfo.AllowDBNull = c.AllowDBNull;
                        columnInfo.IsPrimaryKey = columnIndexs.Find(x => x.IsPrimaryKey) != null;
                        columnInfo.MaxLength = c.MaxLength;
                        columnInfo.Ordinal = c.Ordinal;
                        columnInfo.DataType = columnType != null ? columnType.DataType : "System.Object";
                        tableInfo.Columns.Add(columnInfo);
                    });

                    this.Tables.Add(tableInfo);
                }
            }
            finally
            {
                this.Helper.Close();
            }
            return this.Tables;
        }

        /// <summary>
        /// 转换成 Model 代码
        /// </summary>
        /// <returns></returns>
        public string ToModelCode()
        {
            StringBuilder modelCode = new StringBuilder();
            modelCode.AppendLine(string.Format("namespace {0}", this.ModelNameSpace ?? "Model"));
            modelCode.AppendLine("{");
            this.Tables.ForEach(x => { modelCode.AppendLine(x.ToModelCode()); });
            modelCode.AppendLine("}");
            return modelCode.ToString();
        }

        /// <summary>
        /// 转换成 DAL 代码
        /// </summary>
        /// <returns></returns>
        public string ToDalCode()
        {
            StringBuilder dalCode = new StringBuilder();
            dalCode.AppendLine(string.Format("namespace {0}", this.DALNameSpace ?? "DAL"));
            dalCode.AppendLine("{");
            this.Tables.ForEach(x => { dalCode.AppendLine(x.ToDalCode()); });
            dalCode.AppendLine("}");
            return dalCode.ToString();
        }

        /// <summary>
        /// 转换成 BLL 代码
        /// </summary>
        /// <returns></returns>
        public string ToBllCode()
        {
            StringBuilder bllCode = new StringBuilder();
            bllCode.AppendLine(string.Format("namespace {0}", this.BLLNameSpace ?? "BLL"));
            bllCode.AppendLine("{");
            this.Tables.ForEach(x => { bllCode.AppendLine(x.ToBllCode()); });
            bllCode.AppendLine("}");
            return bllCode.ToString();
        }
    }
}
